#pragma once

#include <QAbstractItemModel>

#include "LeDocumentObject/IDocumentObjectListener.h"

namespace LDO {
    class Document;
    class IDocumentObject;
class DocumentTreeModelPrivate;
class DocumentTreeModel : public QAbstractItemModel, public IDocumentObjectListener
{
    Q_OBJECT
    Q_DECLARE_PRIVATE(DocumentTreeModel)
    QScopedPointer<DocumentTreeModelPrivate> const d_ptr;

public:
    enum
    {
        NameColumn,
        ColumnCount
    };

    explicit DocumentTreeModel(QObject *parent = 0);
    ~DocumentTreeModel();

    void setDocument(Document *document);
    IDocumentObject *documentObject(const QModelIndex &index) const;

    QModelIndex index(const IDocumentObject *object) const;

    // QAbstractItemModel Interface
public:
    QModelIndex index(int row, int column,
                      const QModelIndex &parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex &index) const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override;
    virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
    virtual Qt::ItemFlags flags(const QModelIndex &index) const override;

    //
    // FIXME: All the below have to be moved to DocumentTreeModelPrivate
    //

    // IDocumentObjectListener interface
public:
    virtual void documentObjectAboutToBeInserted(IDocumentObject *parent, IDocumentObject *child, int index) override;
    virtual void documentObjectInserted(IDocumentObject *parent, IDocumentObject *child, int index) override;
    virtual void documentObjectAboutToBeRemoved(IDocumentObject *parent, IDocumentObject *child, int index) override;
    virtual void documentObjectRemoved(IDocumentObject *parent, IDocumentObject *child, int index) override;
    virtual void documentObjectAboutToChangeProperty(const IDocumentObject *object, const QString &name, const QVariant &oldValue) override;
    virtual void documentObjectPropertyChanged(const IDocumentObject *object, const QString &name, const QVariant &newValue) override;
    // helpers
    void startListeningRecursive(IDocumentObject *object);
    void stopListeningRecursive(IDocumentObject *object);
};

}
